#ifndef _TIMER_HPP_
#define	_TIMER_HPP_
/*******************************************************************************
 ** Name: Timer.hpp                                                           **
 ** Description:                                                              **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved 2-clause BSD License                **
 **                                                                           **
 **  Copyright (c) 2009-2010 Barry "Gian" James  <bjames@munixos.net>         **
 **  All rights reserved.                                                     **
 **                                                                           **
 **  Redistribution and use in source and binary forms, with or without       **
 **  modification, are permitted provided that the following conditions are   **
 **  met:                                                                     **
 **                                                                           **
 **  * Redistributions of source code must retain the above copyright notice, **
 **    this list of conditions and the following disclaimer.                  **
 **  * Redistributions in binary form must reproduce the above copyright      **
 **    notice, this list of conditions and the following disclaimer in the    **
 **    documentation and/or other materials provided with the distribution.   **
 **                                                                           **
 **  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS      **
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED **
 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           **
 ** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT        **
 ** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,    **
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  **
 ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR    **
 ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    **
 ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      **
 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        **
 ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              **
 **                                                                           **
 ******************************************************************************/
// Created on March 16, 2010, 9:45 PM
// Modified $Date: 2011-10-22 02:09:07 +0000 (Sat, 22 Oct 2011) $ by $Author: gian.james $

#define Timer_hpp_ID   "$Id: timer.hpp 146 2011-10-22 02:09:07Z gian.james $"

extern "C" {
#include <signal.h>
#include <time.h>
#include <errno.h>
typedef void (*sigFunc)(int,siginfo_t*,void*);
}
#include <boost/signals2>

#define TIMER_OK	0
#define TIMER_ERROR	-1
#define TIMER_TICK_INTERVAL	30
#define TIMER_RESET_INTERVAL 180
#define TIMER_RESET_INTERVAL_INUSE 900
#define TIMER_INTERVAL_MAX	8	// max array size for intervals
//! @class Timer
//! @brief Time manipulation class
//! POSIX.1b interval timer manipulation class with some other timer junk
//! thrown in for good (or bad) measure.
//! timer_create, timer_settime, timer_gettime, timer_getoverrun, timer_delete
//! sigevent, sigval, itimerspec, timespec, tm, timer_t, sigaction
//! All these functions return 0 on success.
class Timer
{
public:
	// timer_create() in constructor
	// Can also pass in a monotonic or thread-specific cpu clock here
    Timer(int, sigFunc, int = _id, clock_t = CLOCK_REALTIME);
    // timer_delete in destructor
    ~Timer();

    // timer_settime() in run(). Can be:
    int		Run(time_t,long,long);	// ABSOLUTE time
    int		Run(long,long,long,long);	// RELATIVE time
    int		Stop();
    // timer_getoverrun()
    int		Overrun();
    // timer_gettime()
    int		Remaining(long &,long &);
    long	Elapsed();
    int		MinPastHour() { return minPastHour; }
    void	MinPastHour(int mph) { minPastHour = mph; }

    //! returns instantaneous time in seconds since epoch
    static time_t	Now() { return time(NULL); }

    //! takes two epoch times and returns tm struct with difference/ie
    //! the amount of time in between the two timestamps
    tm	*	TimeDelta(bool,time_t,time_t);

    void    Alarm(int sec);

    int operator ! () { return status != 0; }
    friend std::ostream & operator << (std::ostream &,const Timer &);

private:
    timer_t		handle;
    int			status;		//! status value of constructor-related functions
    itimerspec	spec;
    // auto-increment our timer id for each timer object to be unique
    int			timerID;
    int			minPastHour;	// ie 15 = 10:15,11:15,12:15, etc

    static int _id;
    static int incr() { return ++_id; }
};

enum class Month { Jan, Feb, Mar, Apr, May, June, July, Aug,
	Sept, Oct, Nov, Dec,
	max
};
struct MonthStrings
{
	const char *	month;
	const char *	abbr;
};
enum class TimeofDayHour { Sunrise = 5, Daytime = 8, Noon = 12, Sunset = 18, Nighttime = 21, Midnight = 0 };
enum class TimeofDay { Sunrise, Daytime, Noon, Sunset, Nighttime, Midnight };
extern const char * TimeofDayStr[];

//! @class TimeManager
//! @brief Manages all the TIMES in the game.  Big task.
class TimeManager
{
public:
	// ctor: initializes with either a new date or from a previous one
	TimeManager(int m, int h, int d, int mo, int y);

	const char *	MonthStr(Month m) { return monthName[(int)m].month; }
	const char *	DaySuffix(int day);
	const char *	DiscordianDate(const char * fmt, bool kb, bool pb);

	// the only public interface into changing the game time
	// this should get updated every 15s by a global timer
	int	IncrMin();

	static struct ti {
		int	min;
		int	hour;
		int	day;
		int	month;
		int year;
	} timeInfo;

	ti		GetTimeOfDay() { return timeInfo; }

private:
	bool	bDoAbsolute;	// if true, based on like 15 after hour else based
							// on relative time lapse from start of check
	int		secIntervals[TIMER_INTERVAL_MAX];
	static MonthStrings monthName[];
	int		IncrHour();
	int		IncrDay();
	int		IncrMonth();
	int		IncrYear();

};

#endif	/* _TIMER_HPP */

